/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.client.veditor.view.instance;

import java.io.ByteArrayInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.tree.DefaultMutableTreeNode;
import offset.nodes.client.chooser.view.NodeChooserDialog;
import offset.nodes.client.chooser.view.QueryResultChooserDialog;
import offset.nodes.client.model.HierarchyTree;
import offset.nodes.client.model.NodeTypes;
import offset.nodes.client.model.Server;
import offset.nodes.client.model.SimpleNamespaceRegistry;
import offset.nodes.client.view.SchemaNodeRenderer;
import offset.nodes.client.view.TreeNodeChooserDialog;
import offset.nodes.client.virtual.model.GetSchemas;
import offset.nodes.client.virtual.model.SimpleQuery;
import offset.nodes.client.virtual.model.jcr.QName;
import offset.nodes.client.virtual.model.jcr.nodetype.NodeTypeDefinition;
import offset.nodes.client.virtual.model.jcr.nodetype.NodeTypeReader;
import offset.nodes.client.view.SimpleDialog;

/**
 *
 * @author  Walter Lütgenau
 */
public class QueryPanel extends javax.swing.JPanel {
    Server server;
    int referenceDirection = SimpleQuery.REFERENCE_NONE;
    SimpleNamespaceRegistry namespaces = SimpleNamespaceRegistry.getInstance();
    NodeTypes types = null;
    String primaryNodeType;
    
    /** Creates new form SecondaryQueryPanel
     * @param server Access to the server
     */
    public QueryPanel(Server server, String primaryNodeType, SimpleQuery queryParameters, boolean selectReferenceProperty) {
        this.server = server;
        this.primaryNodeType = primaryNodeType;
        
        initComponents();
        
        setQueryParameters(queryParameters);
        
        if ( !selectReferenceProperty) {
            referenceLabel.setEnabled(selectReferenceProperty);
            referenceTextfield.setEnabled(selectReferenceProperty);
            referenceFromThisButton.setEnabled(selectReferenceProperty);
            referenceToThisButton.setEnabled(selectReferenceProperty);
        }
    }
    
    public void setQueryParameters(SimpleQuery query) {
        pathTextField.setText(query.getPath());
        nodeTypeTextfield.setText(query.getNodeType());
        referenceTextfield.setText(query.getReferenceProperty());
        referenceDirection = query.getReferenceDirection();
    }
    
    public SimpleQuery getQueryParameters() {
        SimpleQuery query = new SimpleQuery();
        
        query.setPath(pathTextField.getText());
        query.setNodeType(nodeTypeTextfield.getText());
        query.setReferenceProperty(referenceTextfield.getText());
        query.setReferenceDirection(referenceDirection);
        
        return query;
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pathLabel = new javax.swing.JLabel();
        pathTextField = new javax.swing.JTextField();
        newDataPathButton = new javax.swing.JButton();
        existingDataPathButton = new javax.swing.JButton();
        nodeTypeLabel = new javax.swing.JLabel();
        nodeTypeTextfield = new javax.swing.JTextField();
        referenceLabel = new javax.swing.JLabel();
        referenceTextfield = new javax.swing.JTextField();
        referenceFromThisButton = new javax.swing.JButton();
        referenceToThisButton = new javax.swing.JButton();

        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("offset/nodes/client/editor/view/resources/EditorBundle"); // NOI18N
        pathLabel.setText(bundle.getString("query.path")); // NOI18N

        newDataPathButton.setText(bundle.getString("query.anyFolder")); // NOI18N
        newDataPathButton.setPreferredSize(new java.awt.Dimension(67, 23));
        newDataPathButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectNewFolder(evt);
            }
        });

        existingDataPathButton.setText(bundle.getString("query.dataFolder")); // NOI18N
        existingDataPathButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectExistingFolder(evt);
            }
        });

        nodeTypeLabel.setText(bundle.getString("query.nodeType")); // NOI18N

        nodeTypeTextfield.setEditable(false);

        referenceLabel.setText(bundle.getString("query.reference")); // NOI18N

        referenceFromThisButton.setText(bundle.getString("query.referenceToExternal")); // NOI18N
        referenceFromThisButton.setPreferredSize(new java.awt.Dimension(71, 23));
        referenceFromThisButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                SelectPrimariesReferenceProperty(evt);
            }
        });

        referenceToThisButton.setText(bundle.getString("query.referenceFromExternal")); // NOI18N
        referenceToThisButton.setPreferredSize(new java.awt.Dimension(71, 23));
        referenceToThisButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectSecondariesReferenceProperty(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(25, 25, 25)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(referenceLabel)
                    .addComponent(pathLabel)
                    .addComponent(nodeTypeLabel))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(referenceToThisButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(referenceFromThisButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(1, 1, 1)
                        .addComponent(referenceTextfield, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(newDataPathButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(existingDataPathButton))
                    .addComponent(pathTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 263, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGap(1, 1, 1)
                        .addComponent(nodeTypeTextfield, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE)))
                .addGap(85, 85, 85))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(32, 32, 32)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(pathLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(existingDataPathButton)
                    .addComponent(newDataPathButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(32, 32, 32)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(nodeTypeTextfield, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(nodeTypeLabel))
                .addGap(58, 58, 58)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(referenceTextfield, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(referenceLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(referenceFromThisButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(referenceToThisButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(60, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void selectNewFolder(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectNewFolder
        try {
            NodeChooserDialog dialog = new NodeChooserDialog(null, true, server, pathTextField.getText(), "*");
            dialog.setVisible(true);
            if (dialog.getReturnStatus() == NodeChooserDialog.RET_OK)
                pathTextField.setText(dialog.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }//GEN-LAST:event_selectNewFolder

    private void selectExistingFolder(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectExistingFolder
        try {
            QueryResultChooserDialog dialog = new QueryResultChooserDialog(null, true, server, "//element(*," + nodeTypeTextfield.getText() +")");
            dialog.setVisible(true);
            if (dialog.getResult() == SimpleDialog.OK) {
                pathTextField.setText(dialog.getPath());
                
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }//GEN-LAST:event_selectExistingFolder

    private void selectSecondariesReferenceProperty(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectSecondariesReferenceProperty
        QName name = getQName(nodeTypeTextfield.getText());
        DefaultMutableTreeNode querySchemaNode = HierarchyTree.setupHierarchicalTree(name, 
                (NodeTypeDefinition) getTypes().get(name), null, types, true, true);
        TreeNodeChooserDialog chooser = new TreeNodeChooserDialog(null, true, querySchemaNode);
        chooser.setCellRenderer(new SchemaNodeRenderer());
        chooser.setVisible(true);
        if (chooser.getReturnStatus() == TreeNodeChooserDialog.RET_OK) {
            DefaultMutableTreeNode selected = chooser.getSelectedNode();
            referenceTextfield.setText(selected.toString());
            referenceDirection = SimpleQuery.REFERENCE_TO_THIS;
        }
}//GEN-LAST:event_selectSecondariesReferenceProperty

    private void SelectPrimariesReferenceProperty(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_SelectPrimariesReferenceProperty
        QName name = getQName(primaryNodeType);
        DefaultMutableTreeNode querySchemaNode = HierarchyTree.setupHierarchicalTree(name, 
                (NodeTypeDefinition) getTypes().get(name), null, types, true, true);
        TreeNodeChooserDialog chooser = new TreeNodeChooserDialog(null, true, querySchemaNode);
        chooser.setCellRenderer(new SchemaNodeRenderer());
        chooser.setVisible(true);
        if (chooser.getReturnStatus() == TreeNodeChooserDialog.RET_OK) {
            DefaultMutableTreeNode selected = chooser.getSelectedNode();
            referenceTextfield.setText(selected.toString());
            referenceDirection = SimpleQuery.REFERENCE_FROM_THIS;
        }
    }//GEN-LAST:event_SelectPrimariesReferenceProperty
    
    protected QName getQName(String prefixName) {
        return QName.valueOf(namespaces.toQNameString(prefixName));
    }
    
    protected NodeTypes getTypes() {
        try {
            if (types != null)
                return types;
            
            GetSchemas.Response response = (GetSchemas.Response) server.sendRequest(new GetSchemas.Request());            
            types = new NodeTypes(NodeTypeReader.read(new ByteArrayInputStream(response.getSchemaXml().getBytes())));
            
            return types;
        } catch (Exception ex) {
            Logger.getLogger(QueryPanel.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        } 
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton existingDataPathButton;
    private javax.swing.JButton newDataPathButton;
    private javax.swing.JLabel nodeTypeLabel;
    private javax.swing.JTextField nodeTypeTextfield;
    private javax.swing.JLabel pathLabel;
    private javax.swing.JTextField pathTextField;
    private javax.swing.JButton referenceFromThisButton;
    private javax.swing.JLabel referenceLabel;
    private javax.swing.JTextField referenceTextfield;
    private javax.swing.JButton referenceToThisButton;
    // End of variables declaration//GEN-END:variables
    
}
